﻿/**
 * nPnP - neither Perl not PHP
 *
 * Copyright (C) 2009 Christian Moeller
 *
 * This program is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the 
 * Free Software Foundation; either version 3 of the License, or (at your option) 
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; 
 * if not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FParser.Executor;
using System.Threading;
using FParser.Runtime.Libraries.Threading;
using FParser.Parser;

namespace FParser.Runtime.Libraries
{
    class Lib_Thread : IBaseLibrary
    {
        public Lib_Thread()
        {
            this.threadList = new List<ThreadMethodInfo>();
        }

        public ExternalLibraryCall[] Exports
        {
            get
            {
                return new ExternalLibraryCall[] { 
                    thread,
                    threadlist
                };
            }
        }


        private List<ThreadMethodInfo> threadList;

        public ExecutionResult thread(RuntimeScope scope)
        {
            ExecutionResult result = new ExecutionResult();
            if (scope.HasParameter(1))
            {
                string methodName = scope.GetParameter(1);
                if (scope.Methods.Cache.ContainsKey(methodName))
                    __create_thread(methodName, scope);
                else
                    result.State.Result = EnumExecutionResult.TYPE_NOT_FOUND_ERROR;

            }
            return result;
        }

        public ExecutionResult threadlist(RuntimeScope scope)
        {
            int i = 0;
            ExecutionResult result = new ExecutionResult();
            BaseType type = BaseType.CreateAnonymous("");

            foreach (ThreadMethodInfo info in threadList)
            {
                i++;
                BaseType threadInfo = new BaseType(info.methodName);
                threadInfo.Value = info._thread.ThreadState.ToString();
                if (type.ObjTypes.ContainsKey(info.methodName))
                    type.ObjTypes.Add(info.methodName + "_"+i.ToString(), threadInfo);
                else
                    type.ObjTypes.Add(info.methodName, threadInfo);
            }

            result.sValue = type;
            return result;
        }


        private void __create_thread(string method, RuntimeScope scope)
        {
            ThreadMethodInfo tmInfo = new ThreadMethodInfo();
            Thread runtimeThread = new Thread(new ParameterizedThreadStart(__method_thread));
            
            tmInfo.methodName = method;
            tmInfo.scope = scope;
            tmInfo._thread = runtimeThread;

            this.threadList.Add(tmInfo);

            runtimeThread.Start(tmInfo);
        }

        private void __method_thread(object data)
        {
            ThreadMethodInfo info = (ThreadMethodInfo)data;
            List<Expression> method = info.scope.Methods[info.methodName];
            Executor.Executor executor = new FParser.Executor.Executor(method);
            executor.Scope = info.scope;
            executor.Run();
        }
    }
}
